import re
import os
import sys
import pymysql
import yaml
from jinja2 import Template
from typing import List, Dict, Tuple
from pymysql.cursors import DictCursor
from pathlib import Path

class SQLParser:
    """从MySQL数据库读取表结构信息"""
    def __init__(self, db_config: Dict, table_name: str):
        self.db_config = db_config
        self.table_name = table_name
        self.table_comment = ""
        self.fields = []
        self.primary_key = ""
        self.parse()

    def parse(self):
        """从MySQL数据库查询表结构信息"""
        connection = None
        try:
            # 连接数据库
            connection = pymysql.connect(
                host=self.db_config.get('host', 'localhost'),
                port=self.db_config.get('port', 3306),
                user=self.db_config.get('user'),
                password=self.db_config.get('password'),
                database=self.db_config.get('database'),
                cursorclass=DictCursor
            )

            # 查询表注释
            with connection.cursor() as cursor:
                cursor.execute(
                    "SELECT TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s",
                    (self.db_config.get('database'), self.table_name)
                )
                result = cursor.fetchone()
                self.table_comment = result['TABLE_COMMENT'] if result else ''

            # 查询字段信息
            with connection.cursor() as cursor:
                cursor.execute(
                    "SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT "
                    "FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s ORDER BY ORDINAL_POSITION",
                    (self.db_config.get('database'), self.table_name)
                )
                fields = cursor.fetchall()
                for field in fields:
                    self.fields.append({
                        'name': field['COLUMN_NAME'],
                        'type': field['DATA_TYPE'].lower(),
                        'is_nullable': field['IS_NULLABLE'] == 'YES',
                        'comment': field['COLUMN_COMMENT']
                    })

            # 查询主键信息
            with connection.cursor() as cursor:
                cursor.execute(
                    "SELECT COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE "
                    "WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND CONSTRAINT_NAME = 'PRIMARY'",
                    (self.db_config.get('database'), self.table_name)
                )
                pk_result = cursor.fetchone()
                if pk_result:
                    self.primary_key = pk_result['COLUMN_NAME']

        except Exception as e:
            print(f"数据库查询错误: {str(e)}")
            raise
        finally:
            if connection:
                connection.close()

class CodeGenerator:
    """代码生成器"""
    def __init__(self, db_config: Dict, table_name: str, base_package: str):
        self.sql_parser = SQLParser(db_config, table_name)
        self.base_package = base_package
        self.table_name = self.sql_parser.table_name
        self.table_comment = self.sql_parser.table_comment
        self.fields = self.sql_parser.fields
        self.primary_key = self.sql_parser.primary_key
        # 转换为驼峰命名
        self.class_name = self._to_camel_case(self.table_name, upper_first=True)
        self.lower_class_name = self._to_camel_case(self.table_name, upper_first=False)
        self.base_package = base_package
        self.table_name = self.sql_parser.table_name
        self.table_comment = self.sql_parser.table_comment
        self.fields = self.sql_parser.fields
        self.primary_key = self.sql_parser.primary_key
        # 转换为驼峰命名
        self.class_name = self._to_camel_case(self.table_name, upper_first=True)
        self.lower_class_name = self._to_camel_case(self.table_name, upper_first=False)

    def _to_camel_case(self, name: str, upper_first: bool = True) -> str:
        """下划线转驼峰"""
        parts = name.split('_')
        if upper_first:
            return ''.join(part.capitalize() for part in parts)
        else:
            return parts[0] + ''.join(part.capitalize() for part in parts[1:])

    def _sql_type_to_java_type(self, sql_type: str) -> str:
        """SQL类型转Java类型"""
        type_map = {
            'char': 'String',
            'varchar': 'String',
            'text': 'String',
            'int': 'Integer',
            'tinyint': 'Integer',
            'smallint': 'Integer',
            'bigint': 'Long',
            'float': 'Float',
            'double': 'Double',
            'decimal': 'BigDecimal',
            'datetime': 'LocalDateTime',
            'timestamp': 'LocalDateTime',
            'date': 'LocalDate',
            'time': 'LocalTime',
            'boolean': 'Boolean'
        }
        for key in type_map:
            if sql_type.startswith(key):
                return type_map[key]
        return 'String'

    def _get_field_info(self,upper_first:bool) -> List[Dict]:
        """获取字段信息列表"""
        field_list = []
        for field in self.fields:
            java_field_name = self._to_camel_case(field['name'], upper_first=upper_first)
            java_type = self._sql_type_to_java_type(field['type'])
            field_list.append({
                'sql_name': field['name'],
                'java_name': java_field_name,
                'java_type': java_type,
                'comment': field['comment'],
                'is_primary': field['name'] == self.primary_key
            })
        return field_list

    def generate_entity_do(self) -> str:
        """生成DO实体类"""
        template = Template("""
package {{ base_package }}.entity.{{ module }};

import cn.ior.base.entity.BaseDo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Getter;
import lombok.Setter;

{% if has_localdatetime %}
import java.time.LocalDateTime;
{% endif %}

/**
 * {{ table_comment }}Do
 */
@Getter
@Setter
@TableName("`{{ table_name }}`")
public class {{ class_name }}Do extends BaseDo {
{% for field in fields %}
    // 描述: {{ field.comment }} {% if field.is_primary %}
    @TableId(value="`{{ field.sql_name }}`", type=IdType.ASSIGN_UUID)
    {% elif field.sql_name == "create_time" %}@TableField(value="`{{ field.sql_name }}`, fill = FieldFill.INSERT) 
    {% elif field.sql_name == "update_time" %}@TableField(value="`{{ field.sql_name }}`, fill = FieldFill.INSERT_UPDATE) 
    {% else %}@TableField(value="`{{ field.sql_name }}`") {% endif %}
    private {{ field.java_type }} {{ field.java_name }};
{% endfor %}
}
        """)
        field_info = self._get_field_info(False)
        has_localdatetime = any(f['java_type'] == 'LocalDateTime' for f in field_info)
        return template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            table_name=self.table_name,
            fields=field_info,
            has_localdatetime=has_localdatetime
        )

    def generate_entity_bo(self) -> str:
        """生成BO实体类"""
        template = Template("""
package {{ base_package }}.entity.{{ module }};

import cn.ior.base.entity.BaseBo;
import lombok.Getter;
import lombok.Setter;
import java.util.List;

/**
 * {{ table_comment }}Bo
 */
@Getter
@Setter
public class {{ class_name }}Bo extends BaseBo {

    private {{ class_name }}Do {{ lower_class_name }}Do;

    private List<{{ class_name }}Do> {{ lower_class_name }}Dos;

}
        """)
        return template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            lower_class_name=self.lower_class_name
        )

    def generate_mapper(self) -> str:
        """生成Mapper接口"""
        template = Template("""
package {{ base_package }}.dao.{{ module }};

import {{ base_package }}.entity.{{ module }}.{{ class_name }}Do;
import cn.ior.base.dao.BaseMybatisMapper;

public interface {{ class_name }}Mapper extends BaseMybatisMapper<{{ class_name }}Do> {
}
        """)
        return template.render(
            base_package=self.base_package,
            module=self._get_module(),
            class_name=self.class_name
        )

    def generate_service(self) -> str:
        """生成Service接口"""
        template = Template("""
package {{ base_package }}.service.{{ module }};

import cn.ior.base.service.BaseMybatisService;
import {{ base_package }}.entity.{{ module }}.{{ class_name }}Do;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;

/**
 * {{ table_comment }}Service
 */
public interface {{ class_name }}Service extends BaseMybatisService<{{ class_name }}Do> {

    boolean save({{ class_name }}Do {{ lower_class_name }}Do);

    boolean update({{ class_name }}Do {{ lower_class_name }}Do);
    
    boolean saveOrUpdateAll(List<{{ class_name }}Do> {{ lower_class_name }}Dos);

    boolean delete(String id);

    {{ class_name }}Do findById(String id);

    Page<{{ class_name }}Do> list(Page<{{ class_name }}Do> page, {{ class_name }}Do {{ lower_class_name }}Do);

    List<{{ class_name }}Do> listAll({{ class_name }}Do {{ lower_class_name }}Do);

}
        """)
        return template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            lower_class_name=self.lower_class_name
        )

    def generate_service_impl(self) -> str:
        """生成Service实现类"""
        template = Template("""
package {{ base_package }}.service.{{ module }}.impl;

import cn.ior.base.service.BaseMybatisServiceImpl;
import {{ base_package }}.dao.{{ module }}.{{ class_name }}Mapper;
import {{ base_package }}.entity.{{ module }}.{{ class_name }}Do;
import {{ base_package }}.service.{{ module }}.{{ class_name }}Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;

/**
 * {{ table_comment }}ServiceImpl
 */
@Service("{{ lower_class_name }}Service")
@Transactional
public class {{ class_name }}ServiceImpl extends BaseMybatisServiceImpl<{{ class_name }}Mapper, {{ class_name }}Do> implements {{ class_name }}Service {

    /**
     * 保存{{ table_comment }}
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @Override
    public boolean save({{ class_name }}Do {{ lower_class_name }}Do) {
        return super.save({{ lower_class_name }}Do);
    }
    
    /**
     * 更新{{ table_comment }}
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @Override
    public boolean update({{ class_name }}Do {{ lower_class_name }}Do) {
        return super.updateById({{ lower_class_name }}Do);
    }
    
    /**
     * 批量保存或更新{{ table_comment }}
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @Override
    public boolean saveOrUpdateAll(List<{{ class_name }}Do> {{ lower_class_name }}Dos) {
        return super.saveOrUpdateBatch({{ lower_class_name }}Dos);
    }

    /**
     * 删除{{ table_comment }}
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @Override
    public boolean delete(String id) {
        return super.removeById(id);
    }

    /**
     * 根据ID查询{{ table_comment }}
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @Override
    public {{ class_name }}Do findById(String id) {
        return super.getById(id);
    }

    /**
     * 分页查询{{ table_comment }}
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @Override
    public Page<{{ class_name }}Do> list(Page<{{ class_name }}Do> page, {{ class_name }}Do {{ lower_class_name }}Do) {
        LambdaQueryWrapper<{{ class_name }}Do> wrapper = getListQueryWrapper({{ lower_class_name }}Do);
        if (page.orders().isEmpty()) {
            wrapper.orderByAsc({{ class_name }}Do::get{{ primary_key_java_name }});
        }
        return super.page(page, wrapper);
    }

    /**
     * 查询全部{{ table_comment }}
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @Override
    public List<{{ class_name }}Do> listAll({{ class_name }}Do {{ lower_class_name }}Do) {
        LambdaQueryWrapper<{{ class_name }}Do> wrapper = getListQueryWrapper({{ lower_class_name }}Do);
        return super.list(wrapper);
    }

    /**
     * 获取列表查询条件
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    private LambdaQueryWrapper<{{ class_name }}Do> getListQueryWrapper({{ class_name }}Do {{ lower_class_name }}Do) {
        LambdaQueryWrapper<{{ class_name }}Do> wrapper = new LambdaQueryWrapper<>();
        if ({{ lower_class_name }}Do != null) {
            {% for field in fields %} {% if field.java_type == 'String' and not field.is_primary %} if (StringUtils.isNotBlank({{ lower_class_name }}Do.get{{ field.java_name }}())) wrapper.like({{ class_name }}Do::get{{ field.java_name }}, {{ lower_class_name }}Do.get{{ field.java_name }}()); 
            {% elif not field.is_primary %} if ({{ lower_class_name }}Do.get{{ field.java_name }}() != null) wrapper.eq({{ class_name }}Do::get{{ field.java_name }}, {{ lower_class_name }}Do.get{{ field.java_name }}()); 
            {% endif %} {% endfor %}
        }
        return wrapper;
    }
}
        """)
        from datetime import datetime
        current_date = datetime.now().strftime("%Y-%m-%d")
        primary_key_java_name = self._to_camel_case(self.primary_key, upper_first=True)
        return template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            lower_class_name=self.lower_class_name,
            fields=self._get_field_info(True),
            primary_key_java_name=primary_key_java_name,
            current_date=current_date
        )

    def generate_biz(self) -> str:
        """生成BIZ层代码"""
        template = Template("""
package {{ base_package }}.biz.{{ module }};

import cn.ior.base.entity.BaseBo;
import cn.ior.manage.constants.ReturnMsg;
import {{ base_package }}.entity.{{ module }}.{{ class_name }}Bo;
import {{ base_package }}.entity.{{ module }}.{{ class_name }}Do;
import {{ base_package }}.service.{{ module }}.{{ class_name }}Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.List;

/**
 * {{ table_comment }}业务逻辑
 */
@Component
public class {{ class_name }}Biz {

    @Resource
    private {{ class_name }}Service {{ lower_class_name }}Service;

    /**
    * 查询对象列表
    * @author AutoCodeGen
    * @date {{ current_date }}
    */
    public void list({{ class_name }}Bo bo) {
        Page<{{ class_name }}Do> page = new Page<>(bo.getPageNum(), bo.getPageSize());
        BaseBo.setPageOrder(page, bo);
        page = {{ lower_class_name }}Service.list(page, bo.get{{ class_name }}Do());
        bo.set{{ class_name }}Dos(page.getRecords());
        bo.setTotals(page.getTotal());
    }

    /**
    * 根据ID查询对象
    * @author AutoCodeGen
    * @date {{ current_date }}
    */
    public void findById({{ class_name }}Bo bo) {
        Assert.hasText(bo.get{{ class_name }}Do().get{{ primary_key_java_name }}(), ReturnMsg.ID_NOT_EXIST);
        bo.set{{ class_name }}Do({{ lower_class_name }}Service.findById(bo.get{{ class_name }}Do().get{{ primary_key_java_name }}()));
        Assert.notNull(bo.get{{ class_name }}Do(), ReturnMsg.ENTITY_NOT_EXIST);
    }

    /**
    * 根据ID删除对象
    * 如果ID不存在于数据库中, 也提示成功
    * @author AutoCodeGen
    * @date {{ current_date }}
    */
    public void delete({{ class_name }}Bo bo) {
        Assert.hasText(bo.get{{ class_name }}Do().get{{ primary_key_java_name }}(), ReturnMsg.ID_NOT_EXIST);
        {{ lower_class_name }}Service.delete(bo.get{{ class_name }}Do().get{{ primary_key_java_name }}());
    }

    /**
    * 根据ID全量更新对象
    * 如无传入ID则返回失败
    * @author AutoCodeGen
    * @date {{ current_date }}
    */
    public void update({{ class_name }}Bo bo) {
        Assert.hasText(bo.get{{ class_name }}Do().get{{ primary_key_java_name }}(), ReturnMsg.ID_NOT_EXIST);
        boolean flg = {{ lower_class_name }}Service.update(bo.get{{ class_name }}Do());
        Assert.isTrue(flg, ReturnMsg.ENTITY_NOT_EXIST);
    }
    
    /**
    * 保存对象
    * 如有ID则返回失败
    * @author AutoCodeGen
    * @date {{ current_date }}
    */
    public void save({{ class_name }}Bo bo) {
        boolean flg = {{ lower_class_name }}Service.save(bo.get{{ class_name }}Do());
        Assert.isTrue(flg, ReturnMsg.ENTITY_NOT_EXIST);
    }

    /**
    * 保存或更新多个对象
    * @author AutoCodeGen
    * @date {{ current_date }}
    */
    public void saveOrUpdateAll({{ class_name }}Bo bo) {
        Assert.notEmpty(bo.get{{ class_name }}Dos(), ReturnMsg.ENTITY_NOT_EXIST);
        {{ lower_class_name }}Service.saveOrUpdateAll(bo.get{{ class_name }}Dos());
    }

    /**
    * 查询所有数据
    * @author AutoCodeGen
    * @date {{ current_date }}
    */
    public void listAll({{ class_name }}Bo bo) {
        List<{{ class_name }}Do> {{ lower_class_name }}Dos = {{ lower_class_name }}Service.listAll(bo.get{{ class_name }}Do());
        bo.set{{ class_name }}Dos({{ lower_class_name }}Dos);
    }
}
        """)
        from datetime import datetime
        current_date = datetime.now().strftime("%Y-%m-%d")
        primary_key_java_name = self._to_camel_case(self.primary_key, upper_first=True)
        return template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            lower_class_name=self.lower_class_name,
            primary_key_java_name=primary_key_java_name,
            current_date=current_date
        )

    def generate_dto_vo(self) -> Tuple[str, str]:
        """生成QueryVo和ModifyVo"""
        query_vo_template = Template("""
package {{ base_package }}.web.dto.{{ module }}.vo;

import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;

/**
 * {{ table_comment }}查询VO
 */
@Getter
@Setter
public class {{ class_name }}QueryVo {
{% for field in fields %}
    // 描述: {{ field.comment }}
    private {{ field.java_type }} {{ field.java_name }};

{% endfor %}
}
        """)

        modify_vo_template = Template("""
package {{ base_package }}.web.dto.{{ module }}.vo;

import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;

/**
 * {{ table_comment }}修改VO
 */
@Getter
@Setter
public class {{ class_name }}ModifyVo {
{% for field in fields %}
    // 描述: {{ field.comment }}
    private {{ field.java_type }} {{ field.java_name }};

{% endfor %}
}
        """)

        field_info = self._get_field_info(False)
        query_vo = query_vo_template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            fields=field_info
        )
        modify_vo = modify_vo_template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            fields=field_info
        )
        return query_vo, modify_vo

    def generate_dto_req_resp(self) -> Tuple[str, str]:
        """生成Req和Resp DTO"""
        req_template = Template("""
package {{ base_package }}.web.dto.{{ module }};

import cn.ior.base.web.dto.BaseReq;
import cn.ior.manage.web.dto.{{ module }}.vo.{{ class_name }}ModifyVo;
import cn.ior.manage.web.dto.{{ module }}.vo.{{ class_name }}QueryVo;
import jakarta.validation.Valid;
import lombok.Getter;
import lombok.Setter;
import java.util.List;

/**
 * {{ table_comment }}请求消息
 */
@Getter
@Setter
public class {{ class_name }}Req extends BaseReq {

    // 单个业务对象
    @Valid
    private {{ class_name }}ModifyVo {{ lower_class_name }}ModifyVo;
    
    // 批量业务对象
    @Valid
    private List<{{ class_name }}ModifyVo> {{ lower_class_name }}ModifyVos;

    // 查询对象
    private {{ class_name }}QueryVo {{ lower_class_name }}QueryVo;
}
        """)

        resp_template = Template("""
package {{ base_package }}.web.dto.{{ module }};

import cn.ior.base.web.dto.BaseResp;
import cn.ior.manage.web.dto.{{ module }}.vo.{{ class_name }}ModifyVo;
import cn.ior.manage.web.dto.{{ module }}.vo.{{ class_name }}QueryVo;
import lombok.Getter;
import lombok.Setter;
import java.util.List;

/**
 * {{ table_comment }}返回消息
 */
@Getter
@Setter
public class {{ class_name }}Resp extends BaseResp {

    private {{ class_name }}ModifyVo {{ lower_class_name }}ModifyVo;

    private {{ class_name }}QueryVo {{ lower_class_name }}QueryVo;

    private List<{{ class_name }}QueryVo> {{ lower_class_name }}QueryVos;

}
        """)

        req = req_template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            lower_class_name=self.lower_class_name
        )
        resp = resp_template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            lower_class_name=self.lower_class_name
        )
        return req, resp

    def generate_controller(self) -> str:
        """生成Controller"""
        template = Template("""
package {{ base_package }}.web.rest.{{ module }};

import cn.hutool.core.bean.BeanUtil;
import {{ base_package }}.biz.{{ module }}.{{ class_name }}Biz;
import {{ base_package }}.entity.{{ module }}.{{ class_name }}Bo;
import {{ base_package }}.entity.{{ module }}.{{ class_name }}Do;
import {{ base_package }}.web.dto.{{ module }}.{{ class_name }}Req;
import {{ base_package }}.web.dto.{{ module }}.{{ class_name }}Resp;
import {{ base_package }}.web.dto.{{ module }}.vo.{{ class_name }}ModifyVo;
import {{ base_package }}.web.dto.{{ module }}.vo.{{ class_name }}QueryVo;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * {{ table_comment }}接口
 */
@RestController
@RequestMapping("/api/{{ lower_class_name }}")
public class {{ class_name }}Rest {

    @Resource
    private {{ class_name }}Biz {{ lower_class_name }}Biz;

    /**
     * 分页查询
     * 
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @PostMapping("list")
    public {{ class_name }}Resp listRest(@RequestBody {{ class_name }}Req req) {
        {{ class_name }}Bo bo = new {{ class_name }}Bo();
        bo.set{{ class_name }}Do(new {{ class_name }}Do());
        BeanUtil.copyProperties(req, bo);
        BeanUtil.copyProperties(req.get{{ class_name }}QueryVo(), bo.get{{ class_name }}Do());

        {{ lower_class_name }}Biz.list(bo);

        {{ class_name }}Resp resp = new {{ class_name }}Resp();
        resp.set{{ class_name }}QueryVos(BeanUtil.copyToList(bo.get{{ class_name }}Dos(), {{ class_name }}QueryVo.class));
        BeanUtil.copyProperties(bo, resp);
        return resp;
    }

    /**
     * 通过ID查询
     * 
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @PostMapping("findById")
    public {{ class_name }}Resp findByIdRest(@RequestBody {{ class_name }}Req req) {
        {{ class_name }}Bo bo = new {{ class_name }}Bo();
        bo.set{{ class_name }}Do(new {{ class_name }}Do());
        BeanUtil.copyProperties(req, bo);
        BeanUtil.copyProperties(req.get{{ class_name }}QueryVo(), bo.get{{ class_name }}Do());

        {{ lower_class_name }}Biz.findById(bo);

        {{ class_name }}Resp resp = new {{ class_name }}Resp();
        resp.set{{ class_name }}QueryVo(new {{ class_name }}QueryVo());
        BeanUtil.copyProperties(bo.get{{ class_name }}Do(), resp.get{{ class_name }}QueryVo());
        BeanUtil.copyProperties(bo, resp);
        return resp;
    }

    /**
     * 通过ID删除
     * 
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @PostMapping("delete")
    public {{ class_name }}Resp deleteRest(@RequestBody {{ class_name }}Req req) {
        {{ class_name }}Bo bo = new {{ class_name }}Bo();
        bo.set{{ class_name }}Do(new {{ class_name }}Do());
        BeanUtil.copyProperties(req, bo);
        BeanUtil.copyProperties(req.get{{ class_name }}ModifyVo(), bo.get{{ class_name }}Do());

        {{ lower_class_name }}Biz.delete(bo);

        {{ class_name }}Resp resp = new {{ class_name }}Resp();
        BeanUtil.copyProperties(bo, resp);
        return resp;
    }

    /**
     * 更新
     * 
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @PostMapping("update")
    public {{ class_name }}Resp updateRest(@RequestBody @Valid {{ class_name }}Req req) {
        {{ class_name }}Bo bo = new {{ class_name }}Bo();
        bo.set{{ class_name }}Do(new {{ class_name }}Do());
        BeanUtil.copyProperties(req, bo);
        BeanUtil.copyProperties(req.get{{ class_name }}ModifyVo(), bo.get{{ class_name }}Do());

        {{ lower_class_name }}Biz.update(bo);

        {{ class_name }}Resp resp = new {{ class_name }}Resp();
        BeanUtil.copyProperties(bo, resp);
        return resp;
    }

    /**
     * 保存
     * 
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @PostMapping("save")
    public {{ class_name }}Resp saveRest(@RequestBody @Valid {{ class_name }}Req req) {
        {{ class_name }}Bo bo = new {{ class_name }}Bo();
        bo.set{{ class_name }}Do(new {{ class_name }}Do());
        BeanUtil.copyProperties(req, bo);
        BeanUtil.copyProperties(req.get{{ class_name }}ModifyVo(), bo.get{{ class_name }}Do());

        {{ lower_class_name }}Biz.save(bo);

        {{ class_name }}Resp resp = new {{ class_name }}Resp();
        resp.set{{ class_name }}ModifyVo(new {{ class_name }}ModifyVo());
        resp.get{{ class_name }}ModifyVo().set{{ primary_key_java_name }}(bo.get{{ class_name }}Do().get{{ primary_key_java_name }}());
        BeanUtil.copyProperties(bo, resp);
        return resp;
    }

    /**
     * 批量新增或更新
     * 
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @PostMapping("saveOrUpdateAll")
    public {{ class_name }}Resp saveOrUpdateAllRest(@RequestBody @Valid {{ class_name }}Req req) {
        {{ class_name }}Bo bo = new {{ class_name }}Bo();
        BeanUtil.copyProperties(req, bo);
        bo.set{{ class_name }}Dos(BeanUtil.copyToList(req.get{{ class_name }}ModifyVos(), {{ class_name }}Do.class));

        {{ lower_class_name }}Biz.saveOrUpdateAll(bo);

        {{ class_name }}Resp resp = new {{ class_name }}Resp();
        BeanUtil.copyProperties(bo, resp);
        return resp;
    }

    /**
     * 查询所有
     * 
     * @author AutoGenerator
     * @date {{ current_date }}
     */
    @PostMapping("listAll")
    public {{ class_name }}Resp listAllRest(@RequestBody {{ class_name }}Req req) {
        {{ class_name }}Bo bo = new {{ class_name }}Bo();
        bo.set{{ class_name }}Do(new {{ class_name }}Do());
        BeanUtil.copyProperties(req, bo);
        BeanUtil.copyProperties(req.get{{ class_name }}QueryVo(), bo.get{{ class_name }}Do());

        {{ lower_class_name }}Biz.listAll(bo);

        {{ class_name }}Resp resp = new {{ class_name }}Resp();
        resp.set{{ class_name }}QueryVos(BeanUtil.copyToList(bo.get{{ class_name }}Dos(), {{ class_name }}QueryVo.class));
        BeanUtil.copyProperties(bo, resp);
        return resp;
    }

}
        """)
        from datetime import datetime
        current_date = datetime.now().strftime("%Y-%m-%d")
        primary_key_java_name = self._to_camel_case(self.primary_key, upper_first=True)
        return template.render(
            base_package=self.base_package,
            module=self._get_module(),
            table_comment=self.table_comment,
            class_name=self.class_name,
            lower_class_name=self.lower_class_name,
            current_date=current_date,
            primary_key_java_name=primary_key_java_name
        )

    def _get_module(self) -> str:
        """根据表名获取模块名"""
        # 简单假设表名前缀为模块名，如base_data_dict -> base
        return self.table_name.split('_')[0]


    def generate_all(self, code_base_path: str):
        """生成所有层代码"""
        # 生成代码
        output_dir = os.path.join(code_base_path, 'src', 'main', 'java',
                                  base_package.replace('.', os.sep))

        # 创建目录
        os.makedirs(os.path.join(output_dir, 'entity', generator._get_module()), exist_ok=True)
        os.makedirs(os.path.join(output_dir, 'dao', generator._get_module()), exist_ok=True)
        os.makedirs(os.path.join(output_dir, 'service', generator._get_module()), exist_ok=True)
        os.makedirs(os.path.join(output_dir, 'service', generator._get_module(), 'impl'), exist_ok=True)
        os.makedirs(os.path.join(output_dir, 'biz', generator._get_module()), exist_ok=True)
        os.makedirs(os.path.join(output_dir, 'web', 'dto', generator._get_module(), 'vo'), exist_ok=True)
        os.makedirs(os.path.join(output_dir, 'web', 'dto', generator._get_module()), exist_ok=True)
        os.makedirs(os.path.join(output_dir, 'web', 'rest', generator._get_module()), exist_ok=True)

        # 生成并写入文件
        with open(os.path.join(output_dir, 'entity', generator._get_module(), f'{generator.class_name}Do.java'), 'w',
                  encoding='utf-8') as f:
            f.write(generator.generate_entity_do())

        with open(os.path.join(output_dir, 'entity', generator._get_module(), f'{generator.class_name}Bo.java'), 'w',
                  encoding='utf-8') as f:
            f.write(generator.generate_entity_bo())

        with open(os.path.join(output_dir, 'dao', generator._get_module(), f'{generator.class_name}Mapper.java'), 'w',
                  encoding='utf-8') as f:
            f.write(generator.generate_mapper())

        with open(os.path.join(output_dir, 'service', generator._get_module(), f'{generator.class_name}Service.java'), 'w',
                  encoding='utf-8') as f:
            f.write(generator.generate_service())

        with open(os.path.join(output_dir, 'service', generator._get_module(), 'impl',
                               f'{generator.class_name}ServiceImpl.java'), 'w', encoding='utf-8') as f:
            f.write(generator.generate_service_impl())

        with open(os.path.join(output_dir, 'biz', generator._get_module(), f'{generator.class_name}Biz.java'), 'w',
                  encoding='utf-8') as f:
            f.write(generator.generate_biz())

        query_vo, modify_vo = generator.generate_dto_vo()
        with open(os.path.join(output_dir, 'web', 'dto', generator._get_module(), 'vo',
                               f'{generator.class_name}QueryVo.java'), 'w', encoding='utf-8') as f:
            f.write(query_vo)

        with open(os.path.join(output_dir, 'web', 'dto', generator._get_module(), 'vo',
                               f'{generator.class_name}ModifyVo.java'), 'w', encoding='utf-8') as f:
            f.write(modify_vo)

        req_dto, resp_dto = generator.generate_dto_req_resp()
        with open(os.path.join(output_dir, 'web', 'dto', generator._get_module(), f'{generator.class_name}Req.java'), 'w',
                  encoding='utf-8') as f:
            f.write(req_dto)

        with open(os.path.join(output_dir, 'web', 'dto', generator._get_module(), f'{generator.class_name}Resp.java'), 'w',
                  encoding='utf-8') as f:
            f.write(resp_dto)

        with open(os.path.join(output_dir, 'web', 'rest', generator._get_module(), f'{generator.class_name}Rest.java'), 'w',
                  encoding='utf-8') as f:
            f.write(generator.generate_controller())

        print(f"成功生成 {generator.table_name} 相关代码到 {output_dir}")

if __name__ == "__main__":
    code_base_path = r"D:\code\yypbp-ser"

    # 硬编码数据库配置
    db_config = {
        'host': 'localhost',
        'port': 8000,
        'user': 'root',
        'password': 'MA12356',
        'database': 'yypbp'
    }
    base_package = 'cn.ior.manage'

    table_names=['base_system_config','base_system_dict','patient_operation_summary','patient_operation_timing']

    for table_name in table_names:
        # 创建代码生成器
        generator = CodeGenerator(db_config, table_name, base_package)
        generator.generate_all(code_base_path)

